// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef CLOUDAPPSDK_CASITEMQUEUE_H
#define CLOUDAPPSDK_CASITEMQUEUE_H

#include <chrono>
#include <mutex>
#include <deque>
#include <cstdint>

const uint32_t MAX_ITEM_NUM = 100;
const uint32_t INIT_ITEM_NUM = 30;

template <typename T> class CasItemQueue {
public:
    /*
     * @brief: construct
     */
    CasItemQueue() : m_deque(INIT_ITEM_NUM), m_status(true), m_lock() {}

    /*
     * @brief: deconstruct
     */
    ~CasItemQueue()
    {
        m_status = false;
    }

    /*
     * @brief: to add specific item at the end of queue
     * @param [in] item
     */
    void PutItem(const T item)
    {
        std::lock_guard<std::mutex> lockGuard(m_lock);
        if (m_status) {
            while (m_deque.size() >= MAX_ITEM_NUM) {
                m_deque.pop_front();
            }
            m_deque.push_back(item);
        }
    }

    /*
     * @brief: to get specific item by index
     * @param [in] index, the item's sequential position in queue
     */
    T GetItemAt(uint32_t index)
    {
        std::lock_guard<std::mutex> lockGuard(m_lock);
        uint64_t frameTimeStamp = {};
        if (m_status && !m_deque.empty()) {
            frameTimeStamp = m_deque.at(index);
        }
        return frameTimeStamp;
    }

    /*
     * @brief: to get the item number of queue
     */
    uint32_t GetItemNum()
    {
        std::lock_guard<std::mutex> lockGuard(m_lock);
        return m_deque.size();
    }

    /*
     * @brief: to check the queue empty or not
     */
    bool IsEmpty()
    {
        std::lock_guard<std::mutex> lockGuard(m_lock);
        return m_deque.empty();
    }

    /*
     * @brief: clear all the items off the queue
     */
    void ClearQueue()
    {
        std::lock_guard<std::mutex> lockGuard(m_lock);
        m_deque.clear();
    }

private:
    std::deque<T> m_deque = {};
    volatile bool m_status = true;
    std::mutex m_lock = {};
};
#endif // CLOUDAPPSDK_CASITEMQUEUE_H